#!/bin/bash

# MySQL周期全量备份脚本
# 支持每日自动备份、保留策略、备份验证

set -e

# ===== 配置区域 =====
BACKUP_DIR="/home/aoi/mysql-cluster/backup"
MYSQL_SOCK="/home/aoi/mysql-cluster/master/mysql.sock"
MYSQL_USER="root"
MYSQL_PASSWORD="root123456"
MYSQL_HOST="127.0.0.1"
MYSQL_PORT="3306"

# 备份保留天数
RETENTION_DAYS=7

# 备份文件名前缀
BACKUP_PREFIX="mysql_full_backup"

# 日志文件
LOG_FILE="${BACKUP_DIR}/backup.log"

# ===== 函数定义 =====

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a ${LOG_FILE}
}

# 创建备份目录
create_backup_dir() {
    if [ ! -d "${BACKUP_DIR}" ]; then
        mkdir -p ${BACKUP_DIR}
        log "创建备份目录: ${BACKUP_DIR}"
    fi
}

# 全量备份（使用mysqldump）
full_backup_mysqldump() {
    TIMESTAMP=$(date +%Y%m%d_%H%M%S)
    BACKUP_FILE="${BACKUP_DIR}/${BACKUP_PREFIX}_${TIMESTAMP}.sql"
    BACKUP_FILE_GZ="${BACKUP_FILE}.gz"

    log "开始全量备份..."
    log "备份文件: ${BACKUP_FILE_GZ}"

    # 执行备份
    mysqldump \
        --socket=${MYSQL_SOCK} \
        --user=${MYSQL_USER} \
        --password=${MYSQL_PASSWORD} \
        --all-databases \
        --single-transaction \
        --routines \
        --triggers \
        --events \
        --master-data=2 \
        --flush-logs \
        --hex-blob \
        --default-character-set=utf8mb4 \
        2>>${LOG_FILE} | gzip > ${BACKUP_FILE_GZ}

    if [ $? -eq 0 ]; then
        BACKUP_SIZE=$(du -h ${BACKUP_FILE_GZ} | cut -f1)
        log "备份成功！文件大小: ${BACKUP_SIZE}"
        echo ${BACKUP_FILE_GZ}
    else
        log "备份失败！"
        exit 1
    fi
}

# 全量备份（使用XtraBackup - 推荐用于大型数据库）
full_backup_xtrabackup() {
    TIMESTAMP=$(date +%Y%m%d_%H%M%S)
    BACKUP_DIR_XTR="${BACKUP_DIR}/xtrabackup_${TIMESTAMP}"

    log "开始XtraBackup全量备份..."
    log "备份目录: ${BACKUP_DIR_XTR}"

    # 需要先安装: apt install percona-xtrabackup-80
    if command -v xtrabackup &> /dev/null; then
        xtrabackup \
            --backup \
            --target-dir=${BACKUP_DIR_XTR} \
            --datadir=/home/aoi/mysql-cluster/master/data \
            --socket=${MYSQL_SOCK} \
            --user=${MYSQL_USER} \
            --password=${MYSQL_PASSWORD} \
            2>>${LOG_FILE}

        if [ $? -eq 0 ]; then
            # 压缩备份
            tar -czf ${BACKUP_DIR_XTR}.tar.gz -C ${BACKUP_DIR} $(basename ${BACKUP_DIR_XTR})
            rm -rf ${BACKUP_DIR_XTR}

            BACKUP_SIZE=$(du -h ${BACKUP_DIR_XTR}.tar.gz | cut -f1)
            log "XtraBackup备份成功！文件大小: ${BACKUP_SIZE}"
        else
            log "XtraBackup备份失败！"
        fi
    else
        log "XtraBackup未安装，跳过"
    fi
}

# 备份验证
verify_backup() {
    BACKUP_FILE=$1
    log "验证备份文件: ${BACKUP_FILE}"

    # 检查文件是否存在
    if [ ! -f "${BACKUP_FILE}" ]; then
        log "错误：备份文件不存在"
        return 1
    fi

    # 检查文件大小（至少1KB）
    FILE_SIZE=$(stat -c%s "${BACKUP_FILE}")
    if [ ${FILE_SIZE} -lt 1024 ]; then
        log "错误：备份文件太小 (${FILE_SIZE} bytes)"
        return 1
    fi

    # 检查gzip文件完整性
    if [[ ${BACKUP_FILE} == *.gz ]]; then
        gzip -t ${BACKUP_FILE} 2>>${LOG_FILE}
        if [ $? -eq 0 ]; then
            log "备份文件验证通过"
            return 0
        else
            log "错误：备份文件损坏"
            return 1
        fi
    fi

    log "备份文件验证通过"
    return 0
}

# 清理旧备份
cleanup_old_backups() {
    log "清理${RETENTION_DAYS}天前的备份文件..."

    find ${BACKUP_DIR} -name "${BACKUP_PREFIX}_*.sql.gz" -type f -mtime +${RETENTION_DAYS} -exec rm -f {} \;
    find ${BACKUP_DIR} -name "xtrabackup_*.tar.gz" -type f -mtime +${RETENTION_DAYS} -exec rm -f {} \;

    REMAINING_BACKUPS=$(find ${BACKUP_DIR} -name "${BACKUP_PREFIX}_*.sql.gz" -o -name "xtrabackup_*.tar.gz" | wc -l)
    log "剩余备份文件数: ${REMAINING_BACKUPS}"
}

# 发送备份报告（可选）
send_backup_report() {
    BACKUP_FILE=$1
    STATUS=$2

    # 这里可以集成邮件发送或其他通知方式
    # 示例：使用mail命令
    # echo "备份状态: ${STATUS}" | mail -s "MySQL备份报告" admin@example.com

    log "备份报告: ${STATUS}"
}

# 数据库健康检查
health_check() {
    log "执行数据库健康检查..."

    # 检查MySQL是否运行
    if ! mysqladmin -S ${MYSQL_SOCK} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ping &>/dev/null; then
        log "错误：MySQL未运行"
        return 1
    fi

    # 检查磁盘空间（至少需要10GB）
    AVAILABLE_SPACE=$(df -BG ${BACKUP_DIR} | tail -1 | awk '{print $4}' | sed 's/G//')
    if [ ${AVAILABLE_SPACE} -lt 10 ]; then
        log "警告：磁盘空间不足 (${AVAILABLE_SPACE}GB)"
    fi

    log "健康检查通过"
    return 0
}

# 备份统计信息
backup_statistics() {
    log "=== 备份统计 ==="

    TOTAL_BACKUPS=$(find ${BACKUP_DIR} -name "*.sql.gz" -o -name "*.tar.gz" | wc -l)
    TOTAL_SIZE=$(du -sh ${BACKUP_DIR} | cut -f1)
    LATEST_BACKUP=$(ls -t ${BACKUP_DIR}/${BACKUP_PREFIX}_*.sql.gz 2>/dev/null | head -1)

    log "总备份数: ${TOTAL_BACKUPS}"
    log "总大小: ${TOTAL_SIZE}"
    if [ -n "${LATEST_BACKUP}" ]; then
        log "最新备份: $(basename ${LATEST_BACKUP})"
    fi
}

# ===== 主流程 =====
main() {
    log "========== MySQL备份任务开始 =========="

    # 健康检查
    if ! health_check; then
        log "健康检查失败，退出备份"
        exit 1
    fi

    # 创建备份目录
    create_backup_dir

    # 执行全量备份
    BACKUP_FILE=$(full_backup_mysqldump)

    # 验证备份
    if verify_backup "${BACKUP_FILE}"; then
        send_backup_report "${BACKUP_FILE}" "SUCCESS"
    else
        send_backup_report "${BACKUP_FILE}" "FAILED"
        log "备份验证失败"
        exit 1
    fi

    # 可选：XtraBackup备份
    # full_backup_xtrabackup

    # 清理旧备份
    cleanup_old_backups

    # 显示统计信息
    backup_statistics

    log "========== MySQL备份任务完成 =========="
}

# 执行主流程
main
